PartialOrd trait
半順序
f64はPartialOrdトレイトのみを実装している
NaNは他の値と大小が定まらない
GPT-4.icon
PartialOrdトレイトは、Rustで値の順序を比較するための標準的なトレイトです。このトレイトを実装することで、型のインスタンス間で大小比較を行うことができます。PartialOrdを実装している型では、<、>、<=、>=といった比較演算子を使用可能になります。
以下に詳細を解説します。
---
PartialOrd トレイトの定義
PartialOrdは次のように定義されています。
code:rust
pub trait PartialOrd<Rhs = Self>: PartialEq<Rhs> {
fn partial_cmp(&self, other: &Rhs) -> Option<std::cmp::Ordering>;
fn lt(&self, other: &Rhs) -> bool {
matches!(self.partial_cmp(other), Some(std::cmp::Ordering::Less))
}
fn le(&self, other: &Rhs) -> bool {
matches!(
self.partial_cmp(other),
Some(std::cmp::Ordering::Less | std::cmp::Ordering::Equal)
)
}
fn gt(&self, other: &Rhs) -> bool {
matches!(self.partial_cmp(other), Some(std::cmp::Ordering::Greater))
}
fn ge(&self, other: &Rhs) -> bool {
matches!(
self.partial_cmp(other),
Some(std::cmp::Ordering::Greater | std::cmp::Ordering::Equal)
)
}
}
主なポイント
PartialOrdを実装する型はPartialEqも実装する必要があります。
順序比較には等価性が前提となるためです。
2. partial_cmpメソッド
2つの値の順序を比較し、結果をOption<Ordering>として返します。
Orderingは以下の3つの値を持つ列挙型です:
Ordering::Less (<)
Ordering::Equal (==)
Ordering::Greater (>)
比較できない場合はNoneを返します(例:浮動小数点数のNaN)。
3. デフォルト実装
lt(<)、le(<=)、gt(>)、ge(>=)はデフォルトでpartial_cmpを使って実装されています。
---
カスタム型への実装
手動で実装する例
次の例は、2次元のポイントをx座標の値で比較する場合です。
code:rust
use std::cmp::Ordering;
struct Point {
x: i32,
y: i32,
}
impl PartialEq for Point {
fn eq(&self, other: &Self) -> bool {
self.x == other.x
}
}
impl PartialOrd for Point {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
self.x.partial_cmp(&other.x)
}
}
fn main() {
let p1 = Point { x: 1, y: 5 };
let p2 = Point { x: 2, y: 3 };
let p3 = Point { x: 1, y: 10 };
println!("{}", p1 < p2); // true
println!("{}", p1 > p2); // false
println!("{}", p1 == p3); // true
}
#[derive(PartialOrd)] を使う
#[derive(PartialOrd)]を使えば、型のフィールドを順序比較可能にする自動実装が行えます。ただし、すべてのフィールドがPartialOrdを実装している必要があります。
code:rust
struct Point {
x: i32,
y: i32,
}
fn main() {
let p1 = Point { x: 1, y: 5 };
let p2 = Point { x: 2, y: 3 };
println!("{}", p1 < p2); // true
println!("{}", p1 > p2); // false
}
---
PartialOrdの特性
部分順序(Partial Order)
PartialOrdは部分順序を表します。つまり、すべての値が比較可能であるとは限りません。この点がOrd(全順序)との違いです。
部分順序の例
浮動小数点型(f32, f64)ではNaNが存在します。
NaNはNaN < 1.0でもNaN > 1.0でもなく、NaN == NaNですらfalseです。
比較の結果がNoneになるケース
次のように、partial_cmpがNoneを返す場合があります。
code:rust
fn main() {
let a = std::f64::NAN;
let b = 1.0;
println!("{:?}", a.partial_cmp(&b)); // None
println!("{}", a < b); // false
println!("{}", a > b); // false
}
---
OrdはPartialOrdを拡張したトレイトで、すべての値が順序関係を持つ場合に使用されます。
OrdのcmpメソッドはOrderingを返しますが、Optionではないため、すべての値が比較可能であることを保証します。
たとえば、整数型や文字列型はOrdを実装していますが、浮動小数点型(f32, f64)はOrdを実装していません。
---
PartialOrdを使うべき場面
一部の値が比較できない場合(部分順序のケース)。
特殊な比較ロジックをカスタム型に実装したい場合。
Ordではなく、柔軟な比較が必要な場面(例:浮動小数点や非標準的な比較)。